/**
 * 
 */
package com.apache.license.validator;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.security.PublicKey;
import java.security.Signature;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.apache.license.model.LecenceMsg;

/**
 * @author Hou Dayu
 * license验证类
 */
public class LicenseValidate {

	public static LicenseValidate instance;

	private String begintime;

	public synchronized static LicenseValidate getInstance() {
		if (null == instance)
			instance = new LicenseValidate();
		return instance;
	}

	/**
	 * 
	 */
	private LicenseValidate() {
	}

	private LecenceMsg msg = new LecenceMsg();

	/**
	 * <P>验证lecence文件是否有效不验证信息</P>
	 * @param publicpath
	 * @param lecencpath 许可证
	 * @return
	 * @throws Exception
	 */
	public boolean validate(String publicpath, String lecencpath) throws Exception {
		boolean b = false;
		ObjectInputStream in = new ObjectInputStream(new FileInputStream(publicpath));
		PublicKey publickey = (PublicKey) in.readObject();
		in.close();
		in = new ObjectInputStream(new FileInputStream(lecencpath));
		String info = (String) in.readObject();
		info = TeaUtil.decryptByTea(info);

		initLicense(info);

		byte[] sign = (byte[]) in.readObject();
		in.close();
		Signature signcheck = Signature.getInstance("DSA");
		signcheck.initVerify(publickey);
		signcheck.update(info.getBytes());
		if (!signcheck.verify(sign)) {
			b = true;
		} else {
			b = false;
		}
		return b;
	}

	public boolean validate(String value) {
		boolean b = true;
		String info = TeaUtil.decryptByTea(value);
		try {
			initLicense(info);
		} catch (Exception e) {
			b = false;
		}
		return b;
	}

	/**
	 * <P>验证lecence文件是否有效不验证信息</P>
	 * @param jarPath jar地址
	 * @param publicpath
	 * @param lecencpath 许可证
	 * @return
	 * @throws Exception
	 */
	public boolean validate(String jarPath, String publicpath, String lecencpath) throws Exception {
		boolean b = false;
		ObjectInputStream in = new ObjectInputStream(this.getClass().getResourceAsStream(publicpath));
		PublicKey publickey = (PublicKey) in.readObject();
		in.close();
		in = new ObjectInputStream(this.getClass().getResourceAsStream(lecencpath));
		String info = (String) in.readObject();
		info = TeaUtil.decryptByTea(info);

		initLicense(info);

		byte[] sign = (byte[]) in.readObject();
		in.close();
		Signature signcheck = Signature.getInstance("DSA");
		signcheck.initVerify(publickey);
		signcheck.update(info.getBytes());
		if (!signcheck.verify(sign)) {
			b = true;
		} else {
			b = false;
		}
		return b;
	}

	/**
	  * description: 初始化license信息
	  * @param info license配置串
	  * @throws Exception
	 */
	private void initLicense(String info) throws Exception {
		ByteArrayInputStream inx = new ByteArrayInputStream(info.getBytes("UTF-8"));
		SAXReader reader = new SAXReader();
		Document document = reader.read(inx);
		Element root = document.getRootElement();
		String company = "";//root.elementText("company");
		String server_ip = root.elementText("server-ip");
		String server_mac = root.elementText("server-mac");
		String begin_time = root.elementText("begin-time");
		String timeleng = root.elementText("time-leng");
		String usernumber = root.elementText("user-number");
		String isformal = root.elementText("license-formal");
		//DateFormat df = DateFormat.getDateInstance(2);
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		this.msg.setCompany(company);
		this.msg.setBegintime(df.parse(begin_time));
		this.begintime = begin_time;
		this.msg.setServerip(server_ip);
		this.msg.setServermac(server_mac);
		this.msg.setTimeleng(Integer.valueOf(timeleng));
		this.msg.setUsernumber(Integer.valueOf(usernumber));
		this.msg.setIsformal(isformal);
	}

	/**
	 * ip地址是否有效
	 * @param ip
	 * @return
	 */
	public boolean isip(String ip) {
		if (isNull(msg.getServerip())) {
			return false;
		}
		return this.msg.getServerip().equals(ip);
	}

	/**
	 * 确定mac地址是否有效
	 * @param mac
	 * @return
	 */
	public boolean ismac(String mac) {
		if (isNull(msg.getServermac())) {
			return false;
		}
		return this.msg.getServermac().equals(mac);
	}

	/**
	 * 确定有效期
	 * @return
	 */
	public boolean islasttime() {
		long time = new Date().getTime();
		long last = this.msg.getBegintime().getTime()
				+ (Long.valueOf("" + this.msg.getTimeleng()) * 30 * 24 * 60 * 60 * 1000);
		if (time - last > 0) {
			return false;
		} else {
			return true;
		}
	}

	/**
	 * 验证有效期是否在给的天数内到期
	 * @param dayNum 天数
	 * @return
	 */
	public long isTimeByDay(int dayNum) {
		long time = new Date().getTime();
		long last = this.msg.getBegintime().getTime()
				+ (Long.valueOf("" + this.msg.getTimeleng()) * 30 * 24 * 60 * 60 * 1000);
		//long mark = dayNum * 24 * 60 * 60 * 1000;
		long count = time - last;
		if (count > 0) {
			return -1;
		} else {
			long day = (((Math.abs(count) / 1000) / 60) / 60) / 24;
			if (day > dayNum)
				return day - dayNum;
			return day;
		}
	}

	public LecenceMsg getMsg() {
		return msg;
	}

	public void setMsg(LecenceMsg msg) {
		this.msg = msg;
	}

	/**
	 * 是否正试版
	 * @return
	 */
	public boolean isFormal() {
		if ("1".equals(msg.getIsformal()))
			return true;
		return false;
	}

	/**
	 * 确定时间和mac有效期
	 * @return
	 */
	public boolean isEffective() {
		if (isFormal()) {
			String mac = OsUtils.getMacAddress();
			if (isNull(mac))
				return false;
			if (islasttime() && msg.getServermac().indexOf(mac) != -1) {
				return true;
			}
		} else {
			return islasttime();
		}
		return false;
	}

	private boolean isNull(String text) {
		if ("".equals(text) || "null".equalsIgnoreCase(text) || null == text)
			return true;
		else
			return false;
	}

	public String getBegintime() {
		return begintime;
	}

}
